﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using GameLogic.Controls;

namespace CatchTheDot.Phone
{
    public partial class MyGame : UserControl, IGameFeatures
    {
        public MyGame()
        {
            // Required to initialize variables
            InitializeComponent();

            _levels = Levels.Get();
            _currentLevel = _levels[_level];
        }

        private Level[] _levels;
        private int _level = 0;

        public event EventHandler<ScoresChangedEventArgs> ScoresChanged;
        private void OnChangeScore(int points)
        {
            if (ScoresChanged != null)
            {
                ScoresChangedEventArgs args = new ScoresChangedEventArgs();
                args = new ScoresChangedEventArgs();
                args.Scores = points;
                ScoresChanged(this, args);
            }
        }

        public event EventHandler<LivesChangedEventArgs> LivesChanged;
        DispatcherTimer _timer = new DispatcherTimer();
        Random _rnd = new Random();

        public void Start()
        {
            // Stop Timer
            TimeChangedEventArgs args = new TimeChangedEventArgs();
            args.ResetTimer = true;
            TimeChanged(this, args);

            _info.Visibility = System.Windows.Visibility.Visible;
            _level = 1;

            _timer.Stop();
            _currentLevel = Levels.Get()[_level - 1];
        }

        private void ShowNewDot()
        {
            Dot dot = new Dot();
            dot.MouseLeftButtonDown += (s, e) =>
                {
                    dot.Hide();
                    OnChangeScore(1);
                    LayoutRoot.Children.Remove(s as UIElement);
                    _currentDotCount++;

                    if (_currentDotCount >= _currentLevel.DotCount)
                    {
                        LevelFinished();
                    }
                };
            dot.Width = _currentLevel.DotSize;
            dot.Height = _currentLevel.DotSize;
            dot.SetValue(Canvas.LeftProperty, _rnd.Next(480 - (int)_currentLevel.DotSize) - _currentLevel.DotSize / 2);
            dot.SetValue(Canvas.TopProperty, _rnd.Next(750 - (int)_currentLevel.DotSize) - _currentLevel.DotSize / 2);
            LayoutRoot.Children.Add(dot);
        }

        private void LevelFinished()
        {
            _timer.Stop();

            // Reset Time Control in Game
            TimeChangedEventArgs args = new TimeChangedEventArgs();
            args.ResetTimer = true;
            TimeChanged(this, args);
            
            _info.Visibility = System.Windows.Visibility.Visible;

            _infoText.Text = "Super, nächstes Level";
            _level++;
            _currentLevel = _levels[_level];

            _currentDotCount = 0;
        }
        
        int _currentDotCount;
        Level _currentLevel;

        public void Stop()
        {

        }

        public void Pause()
        {
            _timer.Stop();
        }

        public void Resume()
        {
            _timer.Start();
        }

        public bool IsTimeBased
        {
            get { return true; }
        }

        public bool IsLifeBased
        {
            get { return false; }
        }

        public string GameName
        {
            get { return "Catch The Dot"; }
        }

        public TimeSpan GameDuration
        {
            get
            {
                return _currentLevel.GameDuration;
            }
        }

        private void _start_Click(object sender, RoutedEventArgs e)
        {
            StartLevel();
        }

        private void StartLevel()
        {
            _info.Visibility = System.Windows.Visibility.Collapsed;
            LayoutRoot.Children.Clear();
            _currentDotCount = 0;

            TimeChangedEventArgs args = new TimeChangedEventArgs();
            args.ResumeTimer = true;
            TimeChanged(this, args);

            _timer = new DispatcherTimer();
            _timer.Interval = _currentLevel.TimeBetweenDots;
            _timer.Tick += (s, e) =>
            {
                ShowNewDot();
            };
            _timer.Start();
        }

        public event EventHandler<GameOverEventArgs> GameOver;

        public string DeveloperName
        {
            get { return "Oliver Scheer"; }
        }

        public string CompanyName
        {
            get { return "Microsoft Germany"; }
        }

        public string Description
        {
            get { return string.Empty; }
        }

        public Uri SettingsPage
        {
            get { return null; }
        }

        public event EventHandler<TimeChangedEventArgs> TimeChanged;
        private void OnTimeChanged(int seconds)
        {
            if (TimeChanged != null)
            {
                TimeChangedEventArgs args = new TimeChangedEventArgs();
                args.TimeInSeconds = seconds;
                TimeChanged(this, args);
            }
        }

        public void OnScoresChanged(int scores)
        {
        }

        public void OnLivesChanged(int lives)
        {
        }
    }

    public class Level
    {
        public TimeSpan GameDuration { get; set; }
        public TimeSpan DotVisibilityTime { get; set; }
        public TimeSpan TimeBetweenDots { get; set; }
        public double DotSize { get; set; }
        public int DotCount { get; set; }
    }

    public static class Levels
    {
        public static Level[] Get()
        {
            List<Level> levels = new List<Level>();

            for (int i = 1; i < 21; i++)
            {
                Level l = new Level();
                l.DotSize = 100 - i * 4.5;
                l.DotVisibilityTime = new TimeSpan(0, 0, 0, 0, 5000 - i * 250);
                l.GameDuration = new TimeSpan(0, 0, 30);
                l.TimeBetweenDots = new TimeSpan(0, 0, 0, 0, 2500 - i * 100);
                l.DotCount = i * 4;
                levels.Add(l);
            }

            return levels.ToArray();
        }
    }
}